package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.IdAndNumDTO;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.po.LessonPlan;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-12-07
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {


    private  final CourseClient courseClient;

    @Lazy
    @Autowired
    private ILearningRecordService recordService;

    private final CatalogueClient catalogueClient;

    private final LearningRecordMapper recordMapper;
    //添加课程到用户的课表中
    @Override
    public void addUserLessons(Long userId, List<Long> courseIds) {
        //查找课程信息
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(courseIds);
        //判断
        if (CollUtils.isEmpty(simpleInfoList)){
            log.info("课程信息不存在，无法添加到课表");
            return;
        }
        //创建课表对象的集合
        List<LearningLesson> list = new ArrayList<>(simpleInfoList.size());
        //封装过期时间
        for (CourseSimpleInfoDTO infoDTO : simpleInfoList) {
            //创建课表对象
            LearningLesson lesson = new LearningLesson();
            //获得过期时间
            Integer duration = infoDTO.getValidDuration();
            if (duration != null || duration > 0){
                LocalDateTime now = LocalDateTime.now();
                lesson.setCreateTime(now);
                lesson.setExpireTime(now.plusMonths(duration));
            }
            //填充属性
            lesson.setCourseId(infoDTO.getId());
            lesson.setUserId(userId);
            list.add(lesson);
        }
        //批量假数据添加到数据库中
        saveBatch(list);
    }

    /**
     * 分页查询我的课表
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<LearningLessonVO> queryMyLessons(PageQuery pageQuery) {
        //获取当前登录的对象
        Long userId = UserContext.getUser();
        //封装分页对象
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .page(pageQuery.toMpPage("latest_learn_time", false));
        //获得分页查询的结果
        List<LearningLesson> records = page.getRecords();
        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }
        //查询课表信息
        Map<Long,CourseSimpleInfoDTO> cMap = queryCourseSimpleInfoList(records);
        //封装信息
        List<LearningLessonVO> list = new ArrayList<>(records.size());
        for (LearningLesson record : records) {
            //拷贝对象到返回前端的对象中
            LearningLessonVO learningLessonVO = BeanUtils.copyBean(record, LearningLessonVO.class);
            //获得当前课表的课程信息
            CourseSimpleInfoDTO info = cMap.get(record.getCourseId());
            learningLessonVO.setCourseName(info.getName());
            learningLessonVO.setCourseCoverUrl(info.getCoverUrl());
            learningLessonVO.setSections(info.getSectionNum());
            list.add(learningLessonVO);
        }
        return PageDTO.of(page, list);
    }

    //查询课表信息
    private Map<Long, CourseSimpleInfoDTO> queryCourseSimpleInfoList(List<LearningLesson> records) {

        //将课表中信息取出来
        List<Long> ids = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toList());
        //获得课表信息
        List<CourseSimpleInfoDTO> infoList = courseClient.getSimpleInfoList(ids);
        if(CollUtils.isEmpty(infoList)){
            throw new BadRequestException("课程信息不存在");
        }
        //将课程封装成map集合返回
        Map<Long, CourseSimpleInfoDTO> map = infoList.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        return map;
    }


    /**
     * 查询正在学习的课表
     * @return
     */
    @Override
    public LearningLessonVO queryMyCurrentLesson() {
        //获取当前用户
        Long id = UserContext.getUser();
        //查询当前用户的最后一次学习的课表
        LearningLesson lesson = lambdaQuery().eq(LearningLesson::getUserId, id)
                .eq(LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .last("limit 1")
                .one();
        if (lesson == null){
            return null;
        }
        LearningLessonVO lessonVO = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        CourseFullInfoDTO course = courseClient
                .getCourseInfoById(lesson.getCourseId(), false, false);
        if (course == null){
            throw new BadRequestException("课程不存在");
        }
        lessonVO.setCourseName(course.getName());
        lessonVO.setSections(course.getSectionNum());
        lessonVO.setCourseCoverUrl(course.getCoverUrl())    ;
        //获得课表中的课表总数
        Integer count = lambdaQuery().eq(LearningLesson::getUserId, id)
                .count();
        lessonVO.setCourseAmount(count);
        //获取最后一次学习的目录
        List<CataSimpleInfoDTO> list = catalogueClient.batchQueryCatalogue(
                Collections.singleton(lesson.getLatestSectionId()));
        if (CollUtils.isNotEmpty(list)){
            CataSimpleInfoDTO dto = list.get(0);
            lessonVO.setLatestSectionName(dto.getName());
            lessonVO.setLatestSectionIndex(dto.getCIndex());
        }
        return lessonVO;
    }


    /**
     * 删除失效的课程
     * @param courseIds
     */
    @Override
    public void deleteLessons(Long userId,List<Long> courseIds) {
        //根据当前课程id删除课程
        lambdaUpdate().eq(LearningLesson::getUserId,userId)
                .in(LearningLesson::getCourseId, courseIds)
                .remove();
    }


    /**
     * 校验课程是否有效
     * @param courseId
     * @return
     */
    @Override
    public Long isCourseValid(Long courseId) {
//        如果是报名了则返回lessonId，否则返回空
        LearningLesson lesson = lambdaQuery().eq(LearningLesson::getUserId, UserContext.getUser())
                .eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .ne(LearningLesson::getStatus,LessonStatus.EXPIRED)
                .one();
        if (ObjectUtils.isEmpty(lesson)){
            return null;
        }
        return lesson.getId();
    }


    /**
     * 根据id查询用户课表中指定课程状态
     * @param courseId
     * @return
     */
    @Override
    public LearningLessonVO getByIdStatus(Long courseId) {
        LearningLesson lesson = lambdaQuery().eq(LearningLesson::getUserId, UserContext.getUser())
                .eq(LearningLesson::getCourseId, courseId)
                .one();
        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        return vo;
    }


    /**
     * 统计课程学习人数
     * @param courseId 课程id,状态不为3的课程人数
     * @return 学习人数
     */
    @Override
    public Integer countLearningLessonByCourse(Long courseId) {
        Integer count = lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .ne(LearningLesson::getStatus,LessonStatus.EXPIRED)
                .count();
        return count;
    }


    /**
     * 创建学习计划
     * @param lesson
     */
    @Override
    public void createPlan( LessonPlan lesson) {
        //将学习计划添加到数据库中
        LearningLesson one = lambdaQuery().eq(LearningLesson::getCourseId,lesson.getCourseId())
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .one();
        if (ObjectUtils.isEmpty(one)){
            throw new BadRequestException("没有该课程");
        }
        boolean result1 = lambdaUpdate()
                .eq(LearningLesson::getCourseId, lesson.getCourseId())
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .set(LearningLesson::getWeekFreq,lesson.getFreq())
                .set(LearningLesson::getStatus, LessonStatus.LEARNING)
                .set(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
                .update();
    }



    /**
     * 分页查询学习计划进度
     * @param pageQuery
     * @return
     */
    @Override
    public LearningPlanPageVO queryMyPlans(PageQuery pageQuery) {
        //创建对象
        LearningPlanPageVO pageVO = new LearningPlanPageVO();
        //获取当前用户
        Long id = UserContext.getUser();
        //获取本周的起始时间
        LocalDateTime weekBeginTime = DateUtils.getWeekBeginTime(LocalDate.now());
        LocalDateTime weekEndTime = DateUtils.getWeekEndTime(LocalDate.now());
        //获得本周已经学习的小节数量
        Integer count = recordService.lambdaQuery()
                .eq(LearningRecord::getUserId, id)
                .eq(LearningRecord::getFinished, true)
                .gt(LearningRecord::getFinishTime, weekBeginTime)
                .lt(LearningRecord::getFinishTime, weekEndTime)
                .count();
        pageVO.setWeekFinished(count);
        //获得总的计划学习数量
        Integer num = getBaseMapper().queryTotalPlan(id);
        pageVO.setWeekTotalPlan(num);
        //封装返回数据
        //查询课程分页对象
        Page<LearningLesson> lessonPage = lambdaQuery()
                .eq(LearningLesson::getUserId, id)
                .eq(LearningLesson::getPlanStatus,PlanStatus.PLAN_RUNNING)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        pageVO.setTotal(lessonPage.getTotal());
        pageVO.setPages(lessonPage.getPages());
        List<LearningLesson> records = lessonPage.getRecords();
        if (ObjectUtils.isEmpty(records)){
            return pageVO;
        }
        //不为空
        List<LearningPlanVO> list = new ArrayList<>();
        pageVO.setList(list);
        //远程调用
        Set<Long> ids = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(ids);
        Map<Long, CourseSimpleInfoDTO> courseMap = simpleInfoList.stream()
                .collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        //封装三个属性
        //查询记录表
        List<IdAndNumDTO> finishList = recordMapper.countLearnedSections(id,weekBeginTime,weekEndTime);
        Map<Long, Integer> map = IdAndNumDTO.toMap(finishList);
        for (LearningLesson record : records) {
            //转成planvo对象
            LearningPlanVO learningPlanVO = BeanUtils.copyBean(record, LearningPlanVO.class);
            //封装课程名称
            CourseSimpleInfoDTO course = courseMap.getOrDefault(record.getCourseId(), new CourseSimpleInfoDTO());
            learningPlanVO.setCourseName(course.getName());
            //封装每周已学习章节数
            learningPlanVO.setWeekLearnedSections(map.getOrDefault(record.getId(),0));
            //封装课程章节总数
            learningPlanVO.setSections(course.getSectionNum());
            list.add(learningPlanVO);
        }
        return pageVO;
    }
}
